require 'iconv'
require 'unicode'

class String
	def no_html
		str = self.dup
		str.gsub!(/<\/?[^>]*>/, '')
		str.strip!
		str.gsub!('&nbsp;', '')
		str
	end
	
	def self.random(length)
    Array.new(length) { (rand(122-97) + 97).chr }
  end
  
	# cf. Paul Battley, http://po-ru.com/diary/fixing-invalid-utf-8-in-ruby-revisited/
  def validate_utf8
 		Iconv.iconv('UTF-8//IGNORE', 'UTF-8', (self + ' ') ).first[0..-2]
  end
	
	def to_guid
		str = self.dup
		str.no_html.dirify
	end
	
	def no_script
		str = self.dup
		str
	end
	
	def to_utf(from='windows-1251')
    begin
      Iconv.new("utf-8", from).iconv(self)
    rescue Iconv::IllegalSequence => e
      STDERR << "!! Failed converting from UTF-8 -> ISO-8859-1 (#{self}). Already the right charset?"
      self
    end
  end
  
 def lower
		Unicode::downcase(self)
	end
	
	def upcase
		Unicode::upcase(self)
	end
	
	def capitalize
		Unicode::capitalize(self)
	end
  
  # Returns the string formatted according to a pattern.
  #
  # The pattern consists of placeholders and literals. The string is placed in
  # the placeholders, leaving the literals as they are. The result may be
  # truncated or padded if there are more placeholders than strings.
  #
  # Placeholders are '#' or '&'. Each '#' is replaced by one character from
  # the string, or the filler character if the string has no characters left.
  # The '&' is replaced by any remaining characters, or left out of the result
  # if there are no remaining characters. There can only be one '&' in the
  # pattern. If there is no '&', remaining characters are discarded.
  # 
  # '#' or '&' may be replaced by other characters if they are needed as
  # literals.
  #
  # Examples:
  # "123456789".using('###-##-####')
  #    => "123-45-6789"
  # "12345".using('###-##-####')
  #    => "123-45"
  # "12345".using('###-##-####', nil)
  #    => "12345"
  # "12345".using('###-##-####', ' ')
  #    => "123-45-    "
  # "5551212".using ('(###) ###-####', '', true)
  #    => "555-1212"
  # "873555121276668".using ('(###) ###-#### ext &', '', true)
  #    => "(873) 555-1212 ext 76668"
  # "KB5774X".using ('##-&-#')
  #    => "KB-5774-X"
  #
  # Parameters:
  # pattern -- The format string, see above.
  # fill    -- A string for padding. If the empty string, then the pattern is
  #            filled as much as possible, and the rest of the pattern is
  #            truncated. If nil, and the string does not fill the pattern,
  #            the string is returned unchanged.  Otherwise, the string is
  #            padded to fill the pattern, which is not truncated. Defaults to
  #            the empty string.
  # right   -- If true, the pattern is filled from right-to-left instead of
  #            from left-to-right, and truncated on the left instead of the
  #            right if needed. Default is false.
  # fixchar -- The single-character placeholder. Default is '#'.
  # remchar -- The remaining-character placeholder. Default is '&'.
  #
  def using(pattern, fill='', right=false, fixchar='#', remchar='&')

    remCount = pattern.count(remchar)
    raise ArgumentError.new("Too many #{remchar}") if remCount > 1
    raise ArgumentError.new("#{fixchar} too long") if fixchar.length > 1
    raise ArgumentError.new("#{remchar} too long") if remchar.length > 1
    raise ArgumentError.new("#{fill} too long")    if fill.length > 1
    remaining = remCount != 0
    slots = pattern.count(fixchar)

    # Return the string if it doesn't fit and we shouldn't even try,
    if fill.nil?
      return self if self.length < slots
      return self if self.length > slots and !remaining
    end

    # Pad and clone the string if necessary.
    source =  if fill.nil? || fill.empty? then
                self
              elsif right then
                self.rjust(slots, fill)
              else
                self.ljust(slots, fill)
              end
    
    # Truncate the string if necessary.
    if source.length > slots && !remaining then
      source = right ? source[-source.length, source.length] :
                       source[0, source.length]
    end

    # Truncate pattern if needed.
    if !fill.nil? && fill.empty? then
      
      if source.length < slots  # implies '&' can be ignored
        keepCount = source.length # Number of placeholders we are keeping
        leftmost, rightmost = 0, pattern.length - 1
        if right then
          # Look right-to-left until we find the last '#' to keep.
          # Loop starts at 1 because 0th placeholder is in the inject param.
          leftmost = (1...keepCount).inject(pattern.rindex(fixchar)) {
            |leftmost, n| pattern.rindex(fixchar, leftmost - 1) }
        else
          # Look left-to-right until we find the last '#' to keep.
          rightmost = (1...keepCount).inject(pattern.index(fixchar)) {
            |rightmost, n| pattern.index(fixchar, rightmost + 1) }
        end
        pattern = pattern[leftmost..rightmost]
        slots = pattern.count(fixchar)
      end
    
      # Trim empty '&' up to nearest placeholder. If a '&' goes empty, the
      # literals between it and the nearest '#' are probably also unnecessary.
      if source.length == slots then
        if pattern.match("^#{Regexp.escape(remchar)}") then
          pattern = pattern[pattern.index(fixchar) || 0 ... pattern.length]
        elsif pattern.match("#{Regexp.escape(remchar)}$") then
          pattern = pattern[0 ... (pattern.rindex(fixchar) + fixchar.length) || pattern.length]
        end
      end

    end
      
    # Figure out how long the remainder will be when we get to it.
    remSize = source.length - slots
    if remSize < 0 then remSize = 0; end
    
    # Make the result.
    scanner = ::StringScanner.new(pattern)
    sourceIndex = 0
    result = ''
    fixRegexp = Regexp.new(Regexp.escape(fixchar))
    remRegexp = Regexp.new(Regexp.escape(remchar))
    while not scanner.eos?
      if scanner.scan(fixRegexp) then
        result += source[sourceIndex].chr
        sourceIndex += 1
      elsif scanner.scan(remRegexp) then
        result += source[sourceIndex, remSize]
        sourceIndex += remSize
      else
        result += scanner.getch
      end
    end
    
    result
  end
end

class Array
  def to_paginate(page=1, per_page=15)
    pagination_array = WillPaginate::Collection.new(page, per_page, self.size)
    start_index = pagination_array.offset
    end_index = start_index + (per_page - 1)
    array_to_concat = self[start_index..end_index]
    array_to_concat.nil? ? [] : pagination_array.concat(array_to_concat)
  end
  
  def count(*a)
  	inject(0) do |c, e| 
    	if a.size == 1          # suspect, but this is how it works
      	(a[0] == e) ? c + 1 : c
    	else
      	yield(e) ? c + 1 : c
    	end
  	end
	end
	
	def summa
		inject(nil) do |_sum, x| 
			_sum ? _sum + x : x
		end
	end
end

# Extend the Base ActionController to support themes
ActionMailer::Base.class_eval do 
  
  alias_method :__render, :render
  alias_method :__initialize, :initialize

  @current_theme = nil

  attr_reader :current_theme
   
  def initialize(method_name=nil, *parameters)
    if parameters[-1].is_a? Hash and (parameters[-1].include? :theme)
      @current_theme = parameters[-1][:theme]
      parameters[-1].delete :theme
      parameters[-1][:current_theme] = @current_theme
    end
    create!(method_name, *parameters) if method_name
  end
  
  def render(opts)
    body = opts.delete(:body)
    body[:current_theme] = @current_theme
    opts[:file] = "#{mailer_name}/#{opts[:file]}"
    initialize_template_class(body).render(opts)
  end
   
end

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
 %(<span style="font-size:12px;color:red;">#{instance.error_message.kind_of?(Array) ? instance.error_message.first : instance.error_message}</span><br>) + html_tag
end
